/*
  JCM is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  JCM is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with JCM.  If not, see <http://www.gnu.org/licenses/>.
*/
import java.io.*;
import java.net.URL;
import java.awt.*;
import java.util.Enumeration;
import java.util.jar.*;
import javax.swing.*;

/**
 * Classe de suporte a splash screen visando responsividade.
*/
public class SplashHelper implements Runnable
{
  /** Splash padrão para JRE6. */
  private SplashScreen splash;

  /** Fake Splash para JRE5. */
  private SplashWindow window;

  /** Canvas de renderização para qualquer splash. */
  private Graphics2D g2d;

  /** Dimensões do splash screen. */
  private Dimension d;

  /** Métrica da fonte default. */
  private FontMetrics fmt;

  /** Altura default da fonte. */
  private int h;

  /** Máxima altura adicional da fonte no sentido descendente. */
  private int m;

  /** Texto a renderizar na splash screen. */
  private String text;

  /**
   * Constrói a splash screen conforme versão de JRE, apresentando
   * uma mensagem imediatamente.
   *
   * @param firstText Texto da mensagem inicial.
  */
  public SplashHelper(String firstText)
  {
    // check if using Java 5
    if (System.getProperty("java.version").startsWith("1.5")) {
      // pesquisa do nome do arquivo de resource da imagem de splash
      String filename = null;
      try {
        // obtêm a enumeração de todos os arquivos de manifesto de JAR
        Enumeration<?> many = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
        // loop de pesquisa entre os elementos da enumeração
        while (filename == null && many.hasMoreElements())
        {
          // obtêm a url do elemento na forma de string
          String u = ((URL) many.nextElement()).toString();
          // índice do path de execução na url
          int j = u.indexOf(System.getProperty("user.dir"));
          // checa se a url é referente a um jarfile local
          if (j >= 0) {
            // acessa o jarfile local com nome extraído da url
            JarInputStream jis = new JarInputStream(
              new FileInputStream(u.substring(j, u.indexOf('!'))));
            // tenta obter o nome do arquivo de resource correspondente
            // à chave dada entre os atributos do manifesto
            filename = jis.getManifest().getMainAttributes().getValue("SplashScreen-Image");
            jis.close();
          }
        }
      } catch (IOException e) {
        System.err.println(e);
      }
      // checa se o nome do arquivo de resource foi encontrado
      if (filename != null) {
        // instância o fake splash screen
        window = new SplashWindow(filename);
        g2d = (Graphics2D) window.getGraphics();
        d = window.getSize();
      }
    } else if ((splash = SplashScreen.getSplashScreen()) != null) {
      g2d = splash.createGraphics();
      d = splash.getSize();
    }
    // checa se existe canvas de renderização
    if (g2d != null) {
      // prepara o ambiente de renderização
      g2d.setComposite(AlphaComposite.Clear);
      g2d.setPaintMode();
      g2d.setFont(new Font(Font.SANS_SERIF, Font.BOLD, //14));
        // ajuste de tamanho de fonte de acordo com a versão do JVM
        System.getProperty("java.version").startsWith("1.7") ? 13 : 14));
      fmt = g2d.getFontMetrics();
      h = fmt.getHeight();
      m = fmt.getMaxDescent();
      // apresenta a mensagem inicial
      showTask(firstText);
    }
  }

  /**
   * Apresenta texto na porção inferior do canvas de splash.
   *
   * @param text O texto a renderizar no splash.
  */
  public void showTask(String text)
  {
    if (g2d == null || text == null) return;
    this.text = text;
    EventQueue.invokeLater(this);
  }

  /**
   * Renderiza o texto préviamente declarado centralizado na porção
   * inferior do canvas com efeito de sombra e fonte default.
  */
  public void run()
  {
    int x = 30; // margem horizontal
    int w = d.width - 2 * x;  // largura da área de renderização
    int y = 4 * d.height / 5; // margem superior da área de renderização
    // limpa a região de renderização pintando-a com a côr de fundo padrão
    g2d.setColor(Color.WHITE);
    g2d.fillRect(x, y, w, h + m + 1);
    w = (w - SwingUtilities.computeStringWidth(fmt, text)) / 2;
    // renderiza a sombra do texto centralizado
    g2d.setColor(Color.LIGHT_GRAY);
    g2d.drawString(text, (x += w) + 1, (y += h) + 1);
    // renderiza o texto centralizado
    g2d.setColor(myBlue);
    g2d.drawString(text, x, y);
    // atualiza a imagem com texto renderizado
    if (splash != null) splash.update();
  }

  /** Termina a apresentação do splash screen. */
  public void close()
  {
    if (splash != null) splash.close();
    else if (window != null) window.dispose();
  }

  /** Azul personalizado para uso desse aplicativo. */
  private static final Color myBlue = Color.decode("0x0099FF");
}
